package com.ocom.payconfig.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ocom.common.dto.Department;
import com.ocom.common.entity.human.EntityPersonnelInfo;
import com.ocom.common.entity.payconfig.EntityVoucherData;
import com.ocom.common.enums.DataSourceEnum;
import com.ocom.common.enums.MasterSlaveEnum;
import com.ocom.common.enums.ResultEnum;
import com.ocom.common.request.callpackage.BatchSaveByPackageVoucherDto;
import com.ocom.common.request.callpackage.GetPackagePayDetailRequest;
import com.ocom.common.request.callpackage.GetPackagePayDetailResponse;
import com.ocom.common.request.payconfig.CouponsDataExportRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtil;
import com.ocom.common.utils.ResultUtil;
import com.ocom.common.vo.payconfig.*;
import com.ocom.common.vo.webapi.ExcelCouponsVoucherListVo;
import com.ocom.common.vo.webapi.ExcelCouponsVoucherVo;
import com.ocom.mysql.aspect.DataSourceAspect;
import com.ocom.payconfig.client.HumanClientService;
import com.ocom.payconfig.dao.IDaoVoucherData;
import com.ocom.payconfig.service.PersonnelInfoService;
import com.ocom.payconfig.service.VoucherDataService;
import com.ocom.redis.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class VoucherDataServiceImpl extends ServiceImpl<IDaoVoucherData, EntityVoucherData> implements VoucherDataService {

    @Resource
    private IDaoVoucherData iDaoVoucherData;
    @Resource
    private PersonnelInfoService personnelInfoService;
    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private HumanClientService humanClientService;

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Result sendMealCouponByPerson(Long comId, SendMealCouponVo request) {
        EntityPersonnelInfo personnel = personnelInfoService.selectPersonByPCode(request.getComId(), request.getPCode());
        if (personnel == null) {
            return ResultUtil.error(ResultEnum.Err_303);
        }
        EntityVoucherData voucherData = new EntityVoucherData();
        voucherData.setVoucherTypeId(request.getVoucherTypeId());
        voucherData.setStartDate(request.getStartDate());
        voucherData.setStopDate(request.getStopDate());
        voucherData.setGrantTime(new Date());
        voucherData.setComId(request.getComId().intValue());
        voucherData.setNumber(request.getNumber());
        voucherData.setAttribute((byte) 2);
        voucherData.setDataStatus(1);
        voucherData.setPId(personnel.getPId().intValue());
        voucherData.setOrderNo("C" + request.getPCode() + "D" + System.currentTimeMillis());
        voucherData.setVoucherNo(voucherData.getOrderNo() + "P" + String.format("%08d", personnel.getPId()));
        voucherData.setCreateTime(new Date());
        boolean bAddData = this.save(voucherData);
        if (bAddData) {
            return ResultUtil.success(0, "成功", bAddData);
        } else {
            return ResultUtil.error(ResultEnum.Err_2016);
        }
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB,companyId = "comId")
    @Override
    public EntityVoucherData selectVoucherType(Long comId, Long voucherTypeId) {

        QueryWrapper<EntityVoucherData> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("com_id",comId);
        queryWrapper.eq("data_status",4);
        queryWrapper.eq("voucher_type_id",voucherTypeId);
        queryWrapper.last("and stop_date >= DATE(CURDATE()-30) limit 1");
        return this.getOne(queryWrapper);
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Result addCouponsData(Long comId, AddCouponsDataVo addCoupons) {
        ArrayList<EntityVoucherData> evData = new ArrayList<EntityVoucherData>();

        for (Long pId : addCoupons.getPIds()) {
            String strVoucherNo = addCoupons.getOrderNo() + "P" + String.format("%08d", pId);
            if(getvoucherNo(comId,strVoucherNo)){
                continue;
            }
            EntityVoucherData voucherData = new EntityVoucherData();//TODO 性能问题

            voucherData.setComId(addCoupons.getComId().intValue());
            voucherData.setNumber(addCoupons.getVoucherNumber());
            voucherData.setAttribute((byte) 2);
            voucherData.setDataStatus(1);
            voucherData.setPId(pId.intValue());
            voucherData.setOrderNo(addCoupons.getOrderNo());
            voucherData.setVoucherNo(strVoucherNo);
            voucherData.setCreateTime(new Date());
//            if (addCoupons.getItemName() == null) {
//                addCoupons.setItemName("");
//            }
//            voucherData.setItemName(addCoupons.getItemName());
            evData.add(voucherData);
        }
        if(ObjectUtil.isEmpty(evData)){
           return ResultUtil.error(ResultEnum.Err_4079);
        }
        boolean res = this.saveBatch(evData);
        if(res){
            return ResultUtil.success();
        }
        return ResultUtil.error(ResultEnum.Err_2016);
    }


    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Map<String, Object> couponsDataList(Long comId, CouponsDataListVo couponsDataVo) {
        PageHelper.startPage(couponsDataVo.getPage(), couponsDataVo.getSize(), true);
        List<String> deptIds = null;
        if(null != couponsDataVo.getDeptId() && 0 != couponsDataVo.getDeptId()){
            Department department = new Department();
            department.setShowLevel(0);
            department.setComId(comId);
            department.setDeptId(couponsDataVo.getDeptId());
            Result result = humanClientService.getDeptIds(department);
            if (200 != result.getCode()) {
                return null;
            }
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(result.getData()));

            String[] sDeptIds = jsonObject.getString("deptIds").split(",");
            deptIds = Arrays.asList(sDeptIds);
        }

        List<CouponsDataListRVo> list = iDaoVoucherData.couponsDataList(couponsDataVo.getComId(), couponsDataVo.getOrderNo(), deptIds, couponsDataVo.getAccType(), couponsDataVo.getPCode(), couponsDataVo.getPName(), couponsDataVo.getTag(), couponsDataVo.getVoucherTypeId());
        PageInfo<CouponsDataListRVo> pageInfo = new PageInfo<>(list);
        Map<String, Object> map = new HashMap();
        map.put("total", pageInfo.getTotal());
        map.put("list", list);
        return map;
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Boolean changeCouponsNumber(Long comId, ChangeCouponsNumberVo request) {
        UpdateWrapper<EntityVoucherData> update = Wrappers.update();
        update.eq("com_id", request.getComId());
        update.eq("data_status", 1);
        update.eq("order_no", request.getOrderNo());
        if (request.getPIds() != null && request.getPIds().length > 0) {
            update.in("p_id", request.getPIds());
        }
        if (request.getVoucherNumber() > 0) {
            update.ne("number", request.getVoucherNumber());
            update.set("number", request.getVoucherNumber());
            update.set("update_time", new Date());
            this.update(update);
        } else if (request.getVoucherNumber() == 0) {
            this.remove(update);
        }
        return true;
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public CouponsNumberRVo couponsNumber(Long comId, String orderNo) {
//        QueryWrapper<CouponsNumberRVo> query = Wrappers.query();
//        query.eq("com_id",comId);
//        query.eq("order_no",orderNo);
        return iDaoVoucherData.couponsNumber(comId, orderNo);
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB,companyId = "comId")
    public List<GetPackagePayDetailResponse> getPackagePayDetail(Long comId, GetPackagePayDetailRequest request) {
        return iDaoVoucherData.getPackagePayDetail(comId, request.getPId(), request.getOrderNo());
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB,companyId = "comId")
    public Integer batchSaveByPackageVoucher(Long comId, BatchSaveByPackageVoucherDto request) {
        return iDaoVoucherData.batchSaveByPackageVoucher(
                request.getComId(),
                request.getPId(),
                request.getOrderNo(),
                request.getStartDate(),
                request.getStopDate(),
                request.getPackageTypeId());
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Boolean breakCoupons(Long comId, BreakCouponsVo request) {
        UpdateWrapper<EntityVoucherData> update = Wrappers.update();
        update.eq("com_id", request.getComId());
        update.eq("data_status", 4);
        update.eq("order_no", request.getOrderNo());
        update.set("data_status", 10);
        update.set("update_time", new Date());
        return this.update(update);
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Boolean grantCoupons(Long comId, GrantCouponsVo request) {
        UpdateWrapper<EntityVoucherData> update = Wrappers.update();
        update.eq("com_id", request.getComId());
        update.eq("data_status",1);
        update.eq("order_no", request.getOrderNo());

        update.set("data_status",4);
        update.set("voucher_type_id", request.getVoucherTypeId());
        update.set("start_date", DateUtil.strToDateLong(request.getStartDate()));
        update.set("stop_date", DateUtil.strToDateLong(request.getStopDate()));
        update.set("grant_time", new Date());
        return this.update(update);
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.MAIN_DB, companyId = "comId", isMaster = MasterSlaveEnum.MASTER)
    public Boolean importCouponsVoucher(Long comId, ExcelCouponsVoucherListVo excelListCouponsVo) {
        log.info("------批量导入优惠券开始-------");
        if(excelListCouponsVo.getListVoucherData() == null){
            log.info("批量导入优惠券数组为0,返回");
            return false;
        }

        ArrayList<EntityVoucherData> evData = new ArrayList<EntityVoucherData>();

        for(ExcelCouponsVoucherVo excelAddCouponsVo : excelListCouponsVo.getListVoucherData()){
            try {
                EntityPersonnelInfo personnel = personnelInfoService.selectPersonByPCode(comId, excelAddCouponsVo.getPCode());
                Map<String, Object> map = new HashMap<>();
                if (personnel == null) {
                    map.put("errMsg", excelAddCouponsVo.getPCode() + " 人员不存在,跳过此记录");
                    map.put("json", excelAddCouponsVo);
                    redisUtil.leftPush("ImportErr:detail:" + comId, map, 86400l);
                    continue;
                }
                String strVoucherNo = excelAddCouponsVo.getOrderNo() + "P" + String.format("%08d", personnel.getPId());
                if(getvoucherNo(comId,strVoucherNo)){
                    map.put("errMsg", excelAddCouponsVo.getPCode() + " 人员赠券已存在,跳过此记录");
                    map.put("json", excelAddCouponsVo);
                    redisUtil.leftPush("ImportErr:detail:" + comId, map, 86400l);
                    continue;
                }
                else {
                    Long pId = personnel.getPId();

                    EntityVoucherData voucherData = new EntityVoucherData();//TODO 性能问题

                    voucherData.setComId(excelAddCouponsVo.getComId().intValue());
                    voucherData.setNumber(excelAddCouponsVo.getVoucherNumber());
                    voucherData.setAttribute((byte) 2);
                    voucherData.setDataStatus(1);
                    voucherData.setPId(pId.intValue());
                    voucherData.setOrderNo(excelAddCouponsVo.getOrderNo());
                    voucherData.setVoucherNo(excelAddCouponsVo.getOrderNo() + "P" + String.format("%08d", pId));
                    voucherData.setCreateTime(new Date());
                    evData.add(voucherData);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.info("批量导入优惠券异常: 【{}】", excelAddCouponsVo);

            }
        }

        log.info("批量导入优惠券数量: " + excelListCouponsVo.getListVoucherData().size());

        return this.saveBatch(evData);
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Boolean getCouponByNo(Long comId, int status, Date grantTime, String orderNo) {
        LocalDateTime localTime = LocalDateTime.now();
        LocalDateTime startOfTheDay = LocalDate.now().atStartOfDay();
        QueryWrapper<EntityVoucherData> query = Wrappers.query();
        query.select("order_no");
//        query.eq("com_id",comId);
        query.eq("order_no", orderNo);
        query.between("grant_time", startOfTheDay, localTime);
        query.last("limit 1");
        EntityVoucherData data = this.getOne(query);
        if (data == null) {
            return false;
        }
        return true;
    }

    public Boolean getvoucherNo(Long comId, String voucherNo){
        QueryWrapper<EntityVoucherData> query = Wrappers.query();
        query.select("voucher_no");
        query.eq("com_id", comId);
        query.eq("voucher_no", voucherNo);
        query.last("limit 1");
        EntityVoucherData data = this.getOne(query);
        if (data == null) {
            return false;
        }
        return true;
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId")
    public Boolean updateVoucherData(Long comId, EntityVoucherData request) {
        UpdateWrapper<EntityVoucherData> update = Wrappers.update();
        update.eq("com_id", comId);
        update.eq("data_status", 1);
        update.eq("order_no", request.getOrderNo());
        update.set("data_status", 4);
        return this.update(update);
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB, isMaster = MasterSlaveEnum.MASTER, companyId = "comId")
    public Result deleteByIds(Long comId, String ids) {
        String[] sIds = null;
        if (ids == null || ids.equals("0")) {
            sIds = null;
        } else if (ids.contains(",")) {
            sIds = ids.split(",");
        } else {
            sIds = new String[]{ids};
        }
        if(sIds!= null && sIds.length > 0){
            ArrayList<String> list = new ArrayList<>(Arrays.asList(sIds));
            return ResultUtil.success(this.removeByIds(list));
        }else{
            return null;
        }
    }

    @DataSourceAspect(type = DataSourceEnum.PART_DB,companyId = "comId")
    @Override
    public Map<String, Object> selectCouponsDataList(Long comId, CouponsDataExportRequest request) {
        PageHelper.startPage(request.getPage(), request.getSize());
        List<String> deptIds = null;
        if (StringUtils.isNotBlank(request.getDeptIds())){
            String[] depts = request.getDeptIds().split(",");
            deptIds = Arrays.asList(depts);
        }
        List<CouponsDataListRVo> list = iDaoVoucherData.couponsDataList(comId, request.getOrderNo(), deptIds, request.getAccType(), request.getPCode(), request.getPName(), request.getTag(), request.getVoucherTypeId().intValue());
        PageInfo<CouponsDataListRVo> pageInfo = new PageInfo<>(list);
        Map<String, Object> map = new HashMap();
        map.put("total", pageInfo.getTotal());
        map.put("list", list);
        return map;
    }

    @Override
    @DataSourceAspect(type = DataSourceEnum.PART_DB, companyId = "comId", isMaster = MasterSlaveEnum.SLAVE)
    public List<EntityVoucherData>  getPackagePayBySms(Long comId, Long pId) {
        QueryWrapper<EntityVoucherData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("com_id", comId);
        if (pId > 0) {
            queryWrapper.eq("p_id", pId);
        }
        queryWrapper.eq("attribute", "3")
                .eq("data_status", "4")
                .last("and DATE_FORMAT(NOW(), '%Y-%m-%d') >= start_date and DATE_FORMAT(NOW(), '%Y-%m-%d') <= stop_date")
                .select( "com_id","p_id", "start_date" , "stop_date");

        return this.list(queryWrapper);
    }
}
